#include <gtk/gtk.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include "support.h"
#include "file.h"
#include "clist.h"

struct file_ctrl global_file;
/*
  * if you use this progrem first or you delete this folder .easyblog
  * carelessly,so the progrem must make this floder,because we store 
  * all data in this folder.
  */
gboolean create_easyblog_folder(struct file_ctrl *global_file)
{
	const gchar *home;
	gchar tmp[80],string[80];
	gint len;
	FILE *fp_config,*fp_default;
	/*get user home folder*/
	if (!(home= getenv("HOME"))) {
		perror("getenv");
		return FALSE ;
	}
	len=strlen(home)+strlen("/.xyeasyblog")+1;
	global_file->home=(gchar *)malloc(sizeof(gchar)+len);
	if(!global_file->home) {
	   perror("malloc");
	   return FALSE;
	}
	g_snprintf(global_file->home,len,"%s/.xyeasyblog",home);
	if(access(global_file->home,F_OK | R_OK |W_OK)==-1) {
		if(mkdir(global_file->home,0755)==-1) {
			perror("mkdir");
			return FALSE;
		}
	}
	/*
	 * get the path of $HOME/.easyblog/config folder,and if there is no 
	 * this folder,wo must make it to store config information.
	 */
	len=strlen(global_file->home)+strlen("/config")+1;
	global_file->config=(gchar *)malloc(sizeof(gchar)+len);
	if(!global_file->config) {
	   perror("malloc");
	   return FALSE;
	}
	g_snprintf(global_file->config,len,"%s/config",global_file->home);
	if(access(global_file->config,F_OK | R_OK |W_OK)==-1) {
		if(mkdir(global_file->config,0755)==-1) {
			perror("mkdir");
			return FALSE;
		}
	}
	
	len=strlen(global_file->home)+strlen("/tmp")+1;
	global_file->tmp=(gchar *)malloc(sizeof(gchar)+len);
	if(!global_file->tmp) {
	   perror("malloc");
	   return FALSE;
	}
	g_snprintf(global_file->tmp,len,"%s/tmp",global_file->home);
	if(access(global_file->tmp,F_OK | R_OK |W_OK)==-1) {
		if(mkdir(global_file->tmp,0755)==-1) {
			perror("mkdir");
			return FALSE;
		}
	}

	len=strlen(global_file->home)+strlen("/data")+1;
	global_file->data=(gchar *)malloc(sizeof(gchar)+len);
	if(!global_file->data) {
	   perror("malloc");
	   return FALSE;
	}
	g_snprintf(global_file->data,len,"%s/data",global_file->home);
	if(access(global_file->data,F_OK | R_OK |W_OK)==-1) {
		if(mkdir(global_file->data,0755)==-1) {
			perror("mkdir");
			return FALSE;
		}
	}
	/*
	 * from there,we could create file config and default probably 
	 * if theynot exist if there is no config file,wo must create it.
	 */
	g_snprintf(tmp,80,"%s/config",global_file->config);
	if(access(tmp,F_OK | R_OK |W_OK)==-1) {	
		if((fp_config=fopen(tmp,"w"))==NULL) {
			perror("fopen");
			return FALSE;
		}
		strcpy(string,"language= 0\ngroup_nums= 1\n");
		if(fprintf(fp_config,"%s",string)!=strlen(string)) {
			perror("fprintf");
			return FALSE;
		}
		memset(tmp,'\0',80);
		g_snprintf(tmp,80,"%s/default",global_file->data);
		if(access(tmp,F_OK | R_OK |W_OK)==-1) {
			strcpy(string,"default= default\ngroups= default\n");
			if(fprintf(fp_config,"%s",string)!=strlen(string)) {
				perror("fprintf");
				return FALSE;
			}
			create_data_file(global_file->data,"default");
		}
		fclose(fp_config);
	}
	global_file->data_mod=FALSE;
	global_file->modify=FALSE;
	return TRUE;
}
/*
 * this function is used to read config file,get each informations of your set and data file,such
 * as language,default file which will be showed when you start up this program,and every 
 * data file which save your data.in other words,it will initialize global value global_file.
 */
gboolean read_config_file(struct file_ctrl *global_file)
{
	gchar tmp[80];
	gchar string[30];
	FILE *fp_config;
	gchar groups[256];
	guint i,j,len;
	gchar *p,strtok_str[]=" ";
	struct file_list *file;
	struct  file_list *files=NULL,*pnext;
	/*
	 * from there,we read config file to get base information such as 
	 * language ,groups.we  use these informations to detect which 
	 * language wo use,which data file(default group) we will open.
	 */
	#ifdef _DEBUG_
		printf("read_easyblog_folder:\n");
	#endif
	memset(groups,'\0',256);
	g_snprintf(tmp,80,"%s/config",global_file->config);
	if((fp_config=fopen(tmp,"r"))==NULL) {
		perror("fopen");
		return FALSE;
	}
	/*read language set*/
	fscanf(fp_config,"%s %d\n",string,&global_file->language);
	/*read group numbers*/
	fscanf(fp_config,"%s %d\n",string,&global_file->group_nums);
	fscanf(fp_config,"%s %s\n",string,global_file->current);
	fscanf(fp_config,"%s ",string);
	for(i=0;i<global_file->group_nums;i++) {
		fscanf(fp_config,"%s ",string);
		strncat(groups,string,256);
		strncat(groups," ",1);
	}
	len=strlen(groups)+1;
	global_file->groups=(gchar *)malloc(len);
	g_snprintf(global_file->groups,len,"%s",groups);	
	fclose(fp_config);
	
	p = strtok( global_file->groups, strtok_str);
	file=(struct file_list *)malloc(sizeof(struct file_list));
	files=pnext=file;
	for (i = 0;p != NULL &&i < global_file->group_nums;i++) {

		memset(file,'\0',sizeof(struct file_list));
		strncpy(file->name, p,FILE_NAME_LEN);
		read_data_file_info(file,global_file->data);
		/*if this data file is default file,we set it to global_file->cur_file*/
		if(strcmp(p,global_file->current)==0) { 
			global_file->cur_file=file;
		}
		#ifdef _DEBUG_
			printf("file_list:-----------------------\n");
			printf("data=======%s\n",file->name);
			printf("offset=====%d\n",file->offset);
			printf("info_nums==%d\n",file->info_nums);
			printf("col_nums==%d\n",file->col_nums );
			printf("colnums===%s\n",file->columns);
			printf("modify====%d\n",file->modify);
		#endif
		file=(struct file_list *)malloc(sizeof(struct file_list));
		pnext->next=file;
		pnext=pnext->next;
		p = strtok(NULL, strtok_str);
		
	}
	pnext->next=NULL;
	global_file->files=files;
	return TRUE;

}
gboolean read_data_file_info(struct file_list *file,const gchar *path)
{
	gchar tmp[80];
	FILE *fp_data;
	gchar string[30];
	gchar columns[256];
	gint j,len;
	g_snprintf(tmp,80,"%s/%s",path,file->name);
	#ifdef _DEBUG_
		printf("read_easyblog_folder:%s\n",tmp);
	#endif
	if((fp_data=fopen(tmp,"r"))==NULL) {
		perror("fopen");
		return FALSE;
	}
	/*read "info_nums= x"*/
	fscanf(fp_data,"%s %d\n",string,&file->info_nums);
	/*read "col_nums= x"*/
	fscanf(fp_data,"%s %d\n",string,&file->col_nums);
	/*read "columns=姓名 班级 电话 邮箱 博客"*/
	fscanf(fp_data,"%s ",string);

	memset(columns,'\0',256);
	for(j=0;j<file->col_nums;j++) {
		fscanf(fp_data,"%s ",string);
		strncat(columns,string,256);
		strncat(columns," ",1);
	}
	len=strlen(columns);
	file->columns=(gchar *)malloc(sizeof(gchar)*len);
	g_snprintf(file->columns,len,"%s",columns);
	/*save the the offset of recoded start in data file*/
	file->offset=ftell(fp_data);
	file->modify=FALSE;
	fclose(fp_data);
	return TRUE;
}
/*
 * after we use function read_config_file initialize global value global_file,we can use this
 * function to show all group in GtkWidget clist_group.
 */
gboolean show_all_group(struct file_ctrl *global_file,struct clist_struct *clist)
{
	/*clist_group widget has two columns*/
	gchar group[2][MAX_CLIST_NAME];
	gchar *pgroup[2];
	gint i;
	struct file_list *p;
	
	gtk_clist_freeze(GTK_CLIST(clist->clist_group));
	p=global_file->files;
	#ifdef _DEBUG_
		printf("read_default_data_file:\n");
	#endif
	for(i=0;i<global_file->group_nums&&p->next!=NULL;i++) {
		#ifdef _DEBUG_
			printf("--------------------------------\n");
			printf("file_data=%s\nfile_info_nums=%d\nfile_next=%s\n",
					p->name,p->info_nums,
					NULL==p->next?"NULL":"NOT NULL");
		#endif
		memset(group,'\0',2*MAX_CLIST_NAME);
		g_snprintf(group[0],MAX_CLIST_NAME,"%s",p->name);	
		g_snprintf(group[1],MAX_CLIST_NAME,"%d",p->info_nums);
		pgroup[0]=group[0];
		pgroup[1]=group[1];
		p->group_id=i;
		gtk_clist_append(GTK_CLIST(clist->clist_group),(gchar **)pgroup);
		if((strcmp(group[0],global_file->current))==0) {
			gtk_clist_select_row(GTK_CLIST(clist->clist_group),p->group_id,0);
		}
		p=p->next;
	}
	gtk_clist_thaw(GTK_CLIST(clist->clist_group));
	return TRUE;
}
/*
 * read informations from file path+global_file->current to show them in GtkWidget clist_show
 */
gboolean read_data_file_to_show(const gchar *path,
					struct file_ctrl *global_file,struct clist_struct *clist)
{
	gchar tmp[80];
	gint len;
	FILE *fp_default;
	gint i,j;
	gchar info[MAX_COLUMNS][MAX_TEXT_LEN];
	gchar *pinfo[MAX_COLUMNS];
	
	g_snprintf(tmp,80,"%s/%s",path,global_file->current);
	#ifdef _DEBUG_
		printf("read default data file: to show default\n");
	#endif
	if((fp_default=fopen(tmp,"r"))==NULL) {
		perror("fopen");
		return FALSE;
	}
	if(fseek(fp_default,global_file->cur_file->offset,SEEK_SET)==-1) {
		perror("fseek");
		return FALSE;
	}
	memset(info,'\0',MAX_COLUMNS*MAX_TEXT_LEN);
	for(i=0;i<global_file->cur_file->col_nums;i++) {
		pinfo[i]=info[i];
	}
	gtk_clist_freeze(GTK_CLIST(clist->clist_show));
	for(i=0;i<global_file->cur_file->info_nums;i++) {
		for(j=0;j<global_file->cur_file->col_nums;j++) {
			fscanf(fp_default,"%s ",info[j]);
		}
		fscanf(fp_default,"\n");
		gtk_clist_append(GTK_CLIST(clist->clist_show),(gchar **)pinfo);
	}
	if(global_file->cur_file->info_nums)
		gtk_clist_select_row(GTK_CLIST(clist->clist_show),0,0);
	else {
		clist->show_selected_row=-1;
		clist->show_selected_column=-1;
	}
	clist->show_all_row=&global_file->cur_file->info_nums;
	gtk_clist_thaw(GTK_CLIST(clist->clist_show));
	fclose(fp_default);
	return TRUE;
}
/*
 * you know when you select other group,we must switch to it ,it means we should read 
 * another data file,and get the information which will to show,but may be the current
 * information wo had modified and you have not save it.to resolve this problem,we use
 * tmp file to save temporary file.when you exit the program and you are not save,we can
 * present you, and use the tmporary file to save the modify if you want.this function is used
 * to create the tmp file to each data file. we use thread to call this function to increase
 * reaction of our program when it start up.
 */
gboolean create_tmp_file(struct file_ctrl *global_file)
{
	gint i,j;
	gchar tmp[80];
	gchar line[256];
	struct file_list *p;
	FILE *fp_tmp,*fp_data;
	#ifdef _DEBUG_
		printf("create_tmp_file:\n");
	#endif
	p=global_file->files;
	for(i=0;i<global_file->group_nums &&p->next != NULL;i++ ) {		
		g_snprintf(tmp,80,"%s/%s",global_file->data,p->name);
		if((fp_data=fopen(tmp,"r"))==NULL) {
			perror("fopen");
			return FALSE;
		}
		g_snprintf(tmp,80,"%s/%s",global_file->tmp,p->name);
		if((fp_tmp=fopen(tmp,"w"))==NULL) {
			perror("fopen");
			return FALSE;
		}
		for(j=0;j<3+p->info_nums&&!feof(fp_data);j++) {
			if(fgets(line,256,fp_data)==NULL) {
				perror("fgets");
				return FALSE;
			}
			printf("READ:%s",line);

			if(fprintf(fp_tmp,"%s",line)!=strlen(line)) {
				perror("fprintf:");
				return FALSE;
			}
		}
		fclose(fp_tmp);
		fclose(fp_data);
		p=p->next;
	}
	return TRUE;
}
/*
 * create data file
 */
gboolean create_data_file(const gchar *path,const gchar *name)
{
	FILE *fp_data;
	gchar tmp[80],*string;

	string=tmp;
	g_snprintf(tmp,80,"%s/%s",path,name);
	#ifdef _DEBUG_
		printf("create_data_file:----\ncreate file:%s\n",tmp);
	#endif
	if((fp_data=fopen(tmp,"w"))==NULL) {
		perror("fopen");
		return FALSE;
	}
	strcpy(string,"info_nums= 0\ncol_nums= 5\ncolumns= ");
	if(fprintf(fp_data,"%s",string)!=strlen(string)) {
		perror("fprintf");
		fclose(fp_data);
		return FALSE;
	}
	strcpy(string,"姓名 班级 电话 邮箱 博客\n");
	if(fprintf(fp_data,"%s",string)!=strlen(string)) {
		perror("fprintf");
		fclose(fp_data);
		return FALSE;
	}
	fclose(fp_data);
	return TRUE;
}

